home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
DBL Pascal Library
/
Fast-BV
/
FastBitVector.p
< prev
Wrap
Text File
|
1993-04-20
|
21KB
|
728 lines
unit FastBitVector;
{A bit vector (BV) is a fixed-size vector of bits numbered 0..N, where N = size-1.}
{Bit vector sizes range from 0 to MAXINT. The empty vector (size=0) is supported,}
{but not particularly useful… Bit vectors are allocated in Mac handles, and are never}
{locked by this unit; it doesn't buy you anything to lock a bit-vector, so don't bother.}
{This unit defines operations to manipulate both individual bits and entire bit vectors.}
interface
type
BitVector = Handle;
BitVectorSize = 0..MAXINT;
{Call InitFastBitVector once before making any other call.}
procedure InitFastBitVector;
{NewBV returns nil if it can't allocate a BV of the specified length.}
{The BV contents are not initialized.}
function NewBV (length: BitVectorSize): BitVector;
{Call DisposeBV to release the memory occupied by a BV when you}
{don't need it any more. The BV may not be referenced after DisposeBV.}
procedure DisposeBV (theBV: BitVector);
{To find out the length of your BV, use this. Remember that indices}
{run from 0 to length - 1.}
function BVLength (theBV: BitVector): BitVectorSize;
{The following group of operations changes the new destination size to be the}
{minimum of the source and original destination sizes. It's OK for the destination}
{to be the same as a source. The …Cmpl variants complement the bits of src2}
{before applying the operation.}
procedure BVCopy (src, dst: BitVector);
procedure BVBitAND (src1, src2, dst: BitVector);
procedure BVBitANDCmpl (src1, src2, dst: BitVector);
procedure BVBitOR (src1, src2, dst: BitVector);
procedure BVBitORCmpl (src1, src2, dst: BitVector);
procedure BVBitEOR (src1, src2, dst: BitVector);
procedure BVBitEORCmpl (src1, src2, dst: BitVector);
procedure BVBitNOT (src, dst: BitVector);
{BVEqual is true iff the BVs are the same length and same contents.}
function BVEqual (bv1, bv2: BitVector): Boolean;
{BVUnequal is true iff the BVs are different lengths or have different contents.}
function BVUnequal (bv1, bv2: BitVector): Boolean;
{These alter the length of a BV. They do nothing if the newLength is not}
{compatible with the operation, i.e. you can't truncate a BV to make it longer}
{or extend a BV to make it shorter. BVExpand leaves the additional bits undetermined.}
{BVAlterLength changes the size either larger or smaller, leaving any new bits undetermined.}
procedure BVTruncate (bv: BitVector; newLength: BitVectorSize);
function BVExpand (bv: BitVector; newLength: BitVectorSize): OSErr;
function BVExtend1 (bv: BitVector; newLength: BitVectorSize): OSErr;
function BVExtend0 (bv: BitVector; newLength: BitVectorSize): OSErr;
function BVAlterLength (bv: BitVector; newLength: BitVectorSize): OSErr;
{Set or clear all bits at once.}
procedure BVSetAllBits (theBV: BitVector);
procedure BVClearAllBits (theBV: BitVector);
{Test a BV to see whether its bits are all set or all clear.}
function BVTestAllClear (theBV: BitVector): Boolean;
function BVTestAllSet (theBV: BitVector): Boolean;
{These set or clear the specified bit if it falls withing the BV.}
procedure BVSetBit (theBV: BitVector; theBit: Integer);
procedure BVClearBit (theBV: BitVector; theBit: Integer);
{BVTestBit returns the state of the specified bit if it falls within the BV.}
function BVTestBit (theBV: BitVector; theBit: Integer): Boolean;
{BVFindNextSetBit scans the BV for the next set bit beyond the specified index,}
{and updates index to indicate the found bit. When no more bits, index becomes -1.}
{To find all set bits, start with index = -1 and call until index becomes -1 again.}
procedure BVFindNextSetBit (bv: BitVector; var index: Integer);
{BVMoveBits copies a run of bits from the src BV into the dst BV at a specified position.}
{The dst BV is never extended - moved bits are lost if they won't fit into the dst BV.}
procedure BVMoveBits (src: BitVector; start, length: Integer; dst: BitVector; position: Integer);
{BVCatenate extends the first BV with the bits from the second BV.}
function BVCatenate (bv1, bv2: BitVector): OSErr;
{BVLoadBits and BVStoreBits move _only_ the bits (not the size) of a bit-vector to}
{a specified location in memory. You have to be sure the in-memory structure}
{matches the size of the bit vector data. Note that you have to leave space for the}
{entire last byte of the data, even if not all bits are used.}
procedure BVLoadBits (theBV: BitVector; theBits: Ptr);
procedure BVStoreBits (theBV: BitVector; theBits: Ptr);
{The M variants work on data stored at a fixed location in memory. None of these}
{can modify the size of the bit vector. No range checking is done. For some routines,}
{an extra parameter is added to specify the length of the vector in bits.}
procedure BVMClearAllBits (theBits: Ptr; length: BitVectorSize);
function BVMEqual (theBits1, theBits2: Ptr; length: BitVectorSize): Boolean;
procedure BVMSetBit (theBits: Ptr; theBit: Integer);
procedure BVMClearBit (theBits: Ptr; theBit: Integer);
function BVMTestBit (theBits: Ptr; theBit: Integer): Boolean;
implementation
{NOTE: All inline code is documented in Fast-bv.lap.lisp.}
{The general strategy is to perform all operations bytewise (yes, slightly suboptimal in terms of speed,}
{but smaller code) using inline routines, and fix up the boundary bytes with special-case code if needed.}
{We always make sure that any unused bits in the last byte are set to zero.}
type
LookupTables = packed record
masks: packed array[0..7] of SignedByte;
offsets: packed array[0..255] of SignedByte;
end;
LookupTablesPtr = ^LookupTables;
LookupTablesHandle = ^LookupTablesPtr;
var
BVLookups: LookupTablesHandle;
procedure InitFastBitVector;
var
i, v: Integer;
begin
BVLookups := LookupTablesHandle(NewHandleClear(SIZEOF(LookupTables)));
with BVLookups^^ do
begin
v := $FF;
for i := 0 to 7 do
begin
masks[i] := v;
v := BSR(v, 1);
end;
offsets[1] := -1;
offsets[2] := -2;
offsets[4] := -3;
offsets[8] := -4;
offsets[16] := -5;
offsets[32] := -6;
offsets[64] := -7;
offsets[128] := -8;
for i := 1 to 255 do
begin
if offsets[i] <> 0 then
v := offsets[i]
else
offsets[i] := v;
end;
end;
end;
type
BVRec = record
len: BitVectorSize;
case Integer of
0: (
vec: packed array[1..1] of Boolean;
);
1: (
bytes: packed array[1..1] of SignedByte;
);
end;
BVPtr = ^BVRec;
BVHdl = ^BVPtr;
function NewBV (length: BitVectorSize): BitVector;
var
bvH: BVHdl;
begin
bvH := BVHdl(NewHandle(SIZEOF(BitVectorSize) + (length + 7) div 8));
bvH^^.len := length;
NewBV := BitVector(bvH);
end;
procedure DisposeBV (theBV: BitVector);
begin
DisposHandle(Handle(theBV));
end;
function BVLength (theBV: BitVector): BitVectorSize;
begin
BVLength := BVHdl(theBV)^^.len;
end;
function VecBytes (bv: BVHdl): Integer;
begin
VecBytes := (bv^^.len + 7) div 8
end;
procedure ClearEndFill (bv: BVHdl);
var
lastByte, residue: Integer;
begin
lastByte := VecBytes(bv);
residue := bv^^.len mod 8;
if residue > 0 then
with bv^^ do
bytes[lastByte] := BAND(bytes[lastByte], BNOT(BVLookups^^.masks[residue]));
end;
procedure ConformLength (src1, src2, dst: BVHdl);
var
minLen: BitVectorSize;
begin
minLen := src1^^.len;
with src2^^ do
if len < minLen then
minLen := len;
with dst^^ do
begin
if len < minLen then
minLen := len;
if minLen < len then
begin
len := minLen;
SetHandleSize(Handle(dst), SIZEOF(BitVectorSize) + VecBytes(dst));
ClearEndFill(dst);
end;
end;
end;
procedure BVCopy (src, dst: BitVector);
var
bvSH, bvDH: BVHdl;
begin
bvSH := BVHdl(src);
bvDH := BVHdl(dst);
ConformLength(bvSH, bvSH, bvDH);
BlockMove(@bvSH^^.vec, @bvDH^^.vec, VecBytes(bvDH));
end;
procedure BlockFill_Inline (value: SignedByte; block: Ptr; length: Integer);
inline
$321F, $5341, $205F, $301F, $10C0, $51C9, $FFFC;
procedure BVSetAllBits (theBV: BitVector);
var
bvH: BVHdl;
begin
bvH := BVHdl(theBV);
BlockFill_Inline($FF, @bvH^^.vec, VecBytes(bvH));
ClearEndFill(bvH);
end;
function BitIndexOK (theBV: BitVector; theBit: Integer): Boolean;
begin
BitIndexOK := (theBit >= 0) and (theBit < BVHdl(theBV)^^.len);
end;
procedure BVSetBit (theBV: BitVector; theBit: Integer);
var
bvH: BVHdl;
begin
bvH := BVHdl(theBV);
if BitIndexOK(theBV, theBit) then
BitSet(@bvH^^.vec, theBit);
end;
procedure BVClearAllBits (theBV: BitVector);
var
bvH: BVHdl;
begin
bvH := BVHdl(theBV);
BlockFill_Inline($00, @bvH^^.vec, VecBytes(bvH));
end;
procedure BVClearBit (theBV: BitVector; theBit: Integer);
var
bvH: BVHdl;
begin
bvH := BVHdl(theBV);
if BitIndexOK(theBV, theBit) then
BitClr(@bvH^^.vec, theBit);
end;
function BVTestBit (theBV: BitVector; theBit: Integer): Boolean;
var
bvH: BVHdl;
begin
bvH := BVHdl(theBV);
BVTestBit := BitTst(@bvH^^.vec, theBit);
end;
function BlockAllClear_Inline (bv: Ptr; length: Integer): Boolean;
inline
$321F, $5341, $205F, $4A18, $56C9, $FFFC, $57EF, $0001, {}
$442F, $0001;
function BVTestAllClear (theBV: BitVector): Boolean;
var
bvH: BVHdl;
len, byteCount: Integer;
allZero: Boolean;
begin
bvH := BVHdl(theBV);
len := bvH^^.len;
byteCount := VecBytes(bvH);
{$PUSH}
{$R-}
allZero := BAND(bvH^^.bytes[byteCount], BNOT(BVLookups^^.masks[len mod 8])) = 0;
{$POP}
if allZero & (byteCount > 1) then
allZero := BlockAllClear_Inline(@bvH^^.vec, byteCount - 1);
BVTestAllClear := allZero;
end;
function BlockAllSet_Inline (bv: Ptr; length: Integer): Boolean;
inline
$321F, $5341, $205F, $4A18, $57C9, $FFFC, $56EF, $0001, {}
$442F, $0001;
function BVTestAllSet (theBV: BitVector): Boolean;
var
bvH: BVHdl;
len, byteCount: Integer;
allOnes: Boolean;
begin
bvH := BVHdl(theBV);
len := bvH^^.len;
byteCount := VecBytes(bvH);
{$PUSH}
{$R-}
allOnes := BOR(bvH^^.bytes[byteCount], BVLookups^^.masks[len mod 8]) = $FF;
{$POP}
if allOnes & (byteCount > 1) then
allOnes := BlockAllSet_Inline(@bvH^^.vec, byteCount - 1);
BVTestAllSet := allOnes;
end;
function BlockEqual_Inline (bv1, bv2: Ptr; length: Integer): Boolean;
inline
$321F, $5341, $225F, $205F, $B308, $56C9, $FFFC, $57EF, {}
$0001, $442F, $0001;
function BVEqual (bv1, bv2: BitVector): Boolean;
var
bv1H, bv2H: BVHdl;
len: Integer;
begin
bv1H := BVHdl(bv1);
bv2H := bvHdl(bv2);
len := bv1H^^.len;
if len <> bv2H^^.len then
BVEqual := False
else
BVEqual := BlockEqual_Inline(@bv1H^^.vec, @bv2H^^.vec, VecBytes(bv1H));
end;
function BlockUnequal_Inline (bv1, bv2: Ptr; length: Integer): Boolean;
inline
$321F, $5341, $225F, $205F, $B308, $57C9, $FFFC, $56EF, {}
$0001, $442F, $0001;
function BVUnequal (bv1, bv2: BitVector): Boolean;
var
bv1H, bv2H: BVHdl;
len: Integer;
begin
bv1H := BVHdl(bv1);
bv2H := bvHdl(bv2);
len := bv1H^^.len;
if len <> bv2H^^.len then
BVUnequal := True
else
BVUnequal := BlockUnequal_Inline(@bv1H^^.vec, @bv2H^^.vec, VecBytes(bv1H));
end;
procedure BlockAND_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $C019, {}
$14C0, $51C9, $FFF8, $245F;
procedure BVBitAND (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockAND_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
end;
procedure BlockANDCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1019, $4600, {}
$C018, $14C0, $51C9, $FFF6, $245F;
procedure BVBitANDCmpl (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockANDCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
end;
procedure BlockOR_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $8019, {}
$14C0, $51C9, $FFF8, $245F;
procedure BVBitOR (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockOR_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
end;
procedure BlockORCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1019, $4600, {}
$8018, $14C0, $51C9, $FFF6, $245F;
procedure BVBitORCmpl (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockORCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
ClearEndFill(bvDH);
end;
procedure BlockEOR_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1018, $1219, {}
$B300, $14C0, $51C9, $FFF6, $245F;
procedure BVBitEOR (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockEOR_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
end;
procedure BlockEORCmpl_Inline (src1, src2, dst: Ptr; length: Integer);
inline
$2F0A, $321F, $5341, $245F, $225F, $205F, $1219, $4601, {}
$1018, $B300, $14C0, $51C9, $FFF4, $245F;
procedure BVBitEORCmpl (src1, src2, dst: BitVector);
var
bv1H, bv2H, bvDH: BVHdl;
begin
bv1H := BVHdl(src1);
bv2H := BVHdl(src2);
bvDH := BVHdl(dst);
ConformLength(bv1H, bv2H, bvDH);
BlockEORCmpl_Inline(@bv1H^^.vec, @bv2H^^.vec, @bvDH^^.vec, VecBytes(bvDH));
ClearEndFill(bvDH);
end;
procedure BlockNOT_Inline (src, dst: Ptr; length: Integer);
inline
$321F, $5341, $225F, $205F, $1018, $4600, $12C0, $51C9, {}
$FFF8;
procedure BVBitNOT (src, dst: BitVector);
var
bvSH, bvDH: BVHdl;
begin
bvSH := BVHdl(src);
bvDH := BVHdl(dst);
ConformLength(bvSH, bvSH, bvDH);
BlockNOT_Inline(@bvSH^^.vec, @bvDH^^.vec, VecBytes(bvDH));
ClearEndFill(bvDH);
end;
procedure BVTruncate (bv: BitVector; newLength: BitVectorSize);
var
bvH: BVHdl;
begin
bvH := BVHdl(bv);
with bvH^^ do
if newLength < len then
begin
len := newLength;
SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
ClearEndFill(bvH);
end;
end;
function BVExpand (bv: BitVector; newLength: BitVectorSize): OSErr;
var
bvH: BVHdl;
err: OSErr;
begin
bvH := BVHdl(bv);
if newLength > bvH^^.len then
bvH^^.len := newLength;
SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
err := MemError;
BVExpand := err;
if err = noErr then
ClearEndFill(bvH);
end;
function BVAlterLength (bv: BitVector; newLength: BitVectorSize): OSErr;
var
bvH: BVHdl;
err: OSErr;
begin
bvH := BVHdl(bv);
SetHandleSize(Handle(bvH), SIZEOF(BitVectorSize) + VecBytes(bvH));
err := MemError;
BVAlterLength := err;
end;
function BVExtend1 (bv: BitVector; newLength: BitVectorSize): OSErr;
var
bvH: BVHdl;
oldLen: BitVectorSize;
oldByteCount, oldResidue, extraByteCount: Integer;
err: OSErr;
begin
bvH := BVHdl(bv);
oldLen := bvH^^.len;
oldByteCount := VecBytes(bvH);
err := BVExpand(bv, newLength);
BVExtend1 := err;
if err = noErr then
begin
oldResidue := oldLen mod 8;
if oldResidue > 0 then
with bvH^^ do
{$PUSH}
{$R-}
bytes[oldByteCount] := BOR(bytes[oldByteCount], BVLookups^^.masks[oldResidue]);
{$POP}
extraByteCount := VecBytes(bvH) - oldByteCount;
if extraByteCount > 0 then
begin
{$PUSH}
{$R-}
BlockFill_Inline($FF, @bvH^^.bytes[oldByteCount + 1], extraByteCount);
{$POP}
ClearEndFill(bvH);
end;
end;
end;
function BVExtend0 (bv: BitVector; newLength: BitVectorSize): OSErr;
var
bvH: BVHdl;
oldLen: BitVectorSize;
oldByteCount, oldResidue, extraByteCount: Integer;
err: OSErr;
begin
bvH := BVHdl(bv);
oldLen := bvH^^.len;
oldByteCount := VecBytes(bvH);
err := BVExpand(bv, newLength);
BVExtend0 := err;
if err = noErr then
begin
oldResidue := oldLen mod 8;
if oldResidue > 0 then
with bvH^^ do
{$PUSH}
{$R-}
bytes[oldByteCount] := BAND(bytes[oldByteCount], BNOT(BVLookups^^.masks[oldResidue]));
{$POP}
extraByteCount := VecBytes(bvH) - oldByteCount;
if extraByteCount > 0 then
{$PUSH}
{$R-}
BlockFill_Inline($00, @bvH^^.bytes[oldByteCount + 1], extraByteCount);
{$POP}
end;
end;
procedure NextBit_Inline (table: Ptr; bvPtr: Ptr; var index: Integer);
inline {Optimized for relatively sparse bit-vectors}
$48E7, $1020, $225F, $3011, $205F, $245F, $2F09, $3418, {}
$2248, $5240, $B042, $6C36, $3600, $E648, $48C0, $D1C0, {}
$5E42, $E64A, $9440, $5342, $4241, $1218, $C67C, $0007, {}
$C232, $30F8, $6002, $1218, $56CA, $FFFC, $6710, $1232, {}
$1000, $4881, $91C9, $3008, $E748, $D240, $6004, $323C, {}
$FFFF, $225F, $3281, $4CDF, $0408;
procedure BVFindNextSetBit (bv: BitVector; var index: Integer);
begin
NextBit_Inline(@BVLookups^^.offsets, Ptr(bv^), index);
end;
procedure BlockShiftBitsLeft_Inline (src, dst: Ptr; shift, length: Integer);
inline {Shift source data left by 1..7 bits while copying to destination.}
$48E7, $1800, $381F, $5344, $341F, $3602, $4443, $5043, {}
$225F, $205F, $4240, $1018, $E528, $1210, $E629, $8001, {}
$12C0, $51CC, $FFF0, $4CDF, $0018;
procedure BVMoveBits (src: BitVector; start, length: Integer; dst: BitVector; position: Integer);
var
bvS, bvD: BVHdl;
startResidue, positionResidue: Integer;
srcLength, dstLength: Integer;
srcBytesBegin, dstBytesBegin, bytesToCopy, shiftCount, mask, lastDstByte: Integer;
aByte: SignedByte;
begin
{• This is unfinished - The general form is OK, but lots of “fenceposts” need adjusting…}
bvS := BVHdl(src);
bvD := BVHdl(dst);
srcLength := bvS^^.len;
dstLength := bvD^^.len;
if (start < srcLength) and (position < dstLength) then
begin
if start + length > srcLength then
length := srcLength - start;
if position + length > dstLength then
length := dstLength - position;
bytesToCopy := length div 8;
srcBytesBegin := start div 8;
startResidue := start mod 8;
if startResidue > 0 then
begin
srcBytesBegin := srcBytesBegin + 1;
bytesToCopy := bytesToCopy - 1;
end;
dstBytesBegin := position div 8;
lastDstByte := dstBytesBegin + bytesToCopy;
positionResidue := position mod 8;
if positionResidue > 0 then
dstBytesBegin := dstBytesBegin + 1;
if startResidue = positionResidue then
begin
mask := BVLookups^^.masks[positionResidue];
{$PUSH}
{$R-}
bvD^^.bytes[dstBytesBegin] := BOR(BAND(bvS^^.bytes[srcBytesBegin], mask), BAND(bvD^^.bytes[srcBytesBegin], BNOT(mask)));
BlockMove(@bvS^^.bytes[srcBytesBegin], @bvD^^.bytes[dstBytesBegin], bytesToCopy);
{$POP}
mask := BVLookups^^.masks[(position + length) mod 8];
{$PUSH}
{$R-}
bvD^^.bytes[lastDstByte] := BOR(BAND(bvS^^.bytes[srcBytesBegin + bytesToCopy], mask), BAND(bvD^^.bytes[lastDstByte], BNOT(mask)));
{$POP}
end
else
begin
shiftCount := positionResidue - startResidue;
if shiftCount < 0 then
begin
shiftCount := shiftCount + 8;
end;
{$PUSH}
{$R-}
BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin], @aByte, shiftCount, 1);
{$POP}
mask := BVLookups^^.masks[shiftCount];
bvD^^.bytes[dstBytesBegin] := BOR(BAND(aByte, mask), BAND(bvD^^.bytes[srcBytesBegin], BNOT(mask)));
{$PUSH}
{$R-}
BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin], @bvD^^.bytes[dstBytesBegin], shiftCount, bytesToCopy);
{$POP}
mask := BVLookups^^.masks[(position + length) mod 8];
{$PUSH}
{$R-}
BlockShiftBitsLeft_Inline(@bvS^^.bytes[srcBytesBegin + bytesToCopy], @aByte, shiftCount, 1);
bvD^^.bytes[lastDstByte] := BOR(BAND(aByte, mask), BAND(bvD^^.bytes[lastDstByte], BNOT(mask)));
{$POP}
end;
end;
end;
function BVCatenate (bv1, bv2: BitVector): OSErr;
var
bv1Length, bv2Length: Integer;
err: OSErr;
begin
bv1Length := BVLength(bv1);
bv2Length := BVLength(bv2);
err := BVExpand(bv1, bv1Length + bv2Length);
BVCatenate := err;
if err = noErr then
BVMoveBits(bv2, 0, bv2Length, bv1, bv1Length);
end;
procedure BVLoadBits (theBV: BitVector; theBits: Ptr);
begin
with BVHdl(theBV)^^ do
BlockMove(theBits, @bytes, VecBytes(BVHdl(theBV)));
end;
procedure BVStoreBits (theBV: BitVector; theBits: Ptr);
begin
with BVHdl(theBV)^^ do
BlockMove(@bytes, theBits, VecBytes(BVHdl(theBV)));
end;
procedure BVMClearAllBits (theBits: Ptr; length: BitVectorSize);
begin
BlockFill_Inline($00, theBits, (length + 7) div 8);
end;
function BVMEqual (theBits1, theBits2: Ptr; length: BitVectorSize): Boolean;
begin
BVMEqual := BlockEqual_Inline(theBits1, theBits2, (length + 7) div 8);
end;
procedure BVMSetBit (theBits: Ptr; theBit: Integer);
begin
BitSet(theBits, theBit);
end;
procedure BVMClearBit (theBits: Ptr; theBit: Integer);
begin
BitClr(theBits, theBit);
end;
function BVMTestBit (theBits: Ptr; theBit: Integer): Boolean;
begin
BVMTestBit := BitTst(theBits, theBit);
end;
end.